package com.mobimap.nhom9.gui.DataInfo;

final public class MapHandle {
	static final double MinLatitude = -85.05112878;
	static final double MaxLatitude = 85.05112878;
	static final double MinLongitude = -177;
	static final double MaxLongitude = 177;
    static Size tileDefaultSize = new Size(256, 256);
    
    public MapHandle(){
    
    }

    static public Point ToPoint(Point geoCoordinate, int zoom)
    {
        Point ret = new Point();
        geoCoordinate.setLatitude(Clip(geoCoordinate.getLatitude(), MinLatitude, MaxLatitude));
        geoCoordinate.setLogitude(Clip(geoCoordinate.getLogitude(), MinLongitude, MaxLongitude));

        double x = (geoCoordinate.getLogitude() + 180) / 360;
        double sinLatitude = Math.sin(geoCoordinate.getLatitude() * Math.PI / 180);
        double y = 0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI);

        Size s = GetTileMatrixSizePixel(zoom);
        double mapSizeX = s.getWidth();
        double mapSizeY = s.getHeight();

        ret.setLogitude(Clip(x * mapSizeX + 0.5, 0, mapSizeX - 1));
        ret.setLatitude(Clip(y * mapSizeY + 0.5, 0, mapSizeY - 1));

        return ret;
    }
    
    public static Point ToGeographicCoordinate(Point point, int zoom)
    {
        Point ret = new Point();
        Size s = GetTileMatrixSizePixel(zoom);
        double mapSizeX = s.getWidth();
        double mapSizeY = s.getHeight();
        double xx = (Clip(point.getLogitude(), 0, mapSizeX - 1) / mapSizeX) - 0.5;
        double yy = 0.5 - (Clip(point.getLatitude(), 0, mapSizeY - 1) / mapSizeY);
        ret.setLatitude(90 - 360 * Math.atan(Math.exp(-yy * 2 * Math.PI)) / Math.PI);
        ret.setLogitude(360 * xx);
        return ret;
    }
    
    private static double Clip(double x, double min, double max){
    	return Math.max(Math.min(x, max), min);
    }
    
    private static Size GetTileMatrixSizePixel(int zoom){
        Size s = GetTileMatrixSizeXY(zoom);
        return new Size(s.getWidth() 
        		* tileDefaultSize.getWidth(), s.getHeight() 
        		* tileDefaultSize.getHeight());
        
    }

    private static Size GetTileMatrixMaxXY(int zoom){
        int xy = (1 << zoom);
        return new Size(xy - 1, xy - 1);
    }

    private static Size GetTileMatrixMinXY(int zoom){
        return new Size(0, 0);
    }

    private static Size GetTileMatrixSizeXY(int zoom){
        Size sMin = GetTileMatrixMinXY(zoom);
        Size sMax = GetTileMatrixMaxXY(zoom);

        return new Size(sMax.getWidth() 
        		- sMin.getWidth() + 1, sMax.getHeight() 
        		- sMin.getHeight() + 1);
    }
}
